package com.xuecheng.ucenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.ucenter.mapper.XcMenuMapper;
import com.xuecheng.ucenter.mapper.XcUserMapper;
import com.xuecheng.ucenter.model.dto.AuthParamsDto;
import com.xuecheng.ucenter.model.dto.XcUserExt;
import com.xuecheng.ucenter.model.po.XcMenu;
import com.xuecheng.ucenter.model.po.XcUser;
import com.xuecheng.ucenter.service.AuthService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import springfox.documentation.spring.web.json.Json;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author shiminghui
 * @date 2024/9/6 17:26
 * @description: TODO
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class UserServiceImpl implements UserDetailsService {

    private final ApplicationContext applicationContext;
    private final XcMenuMapper xcMenuMapper;


    /**
     * 方法会查询数据库,并将查询数据封装成userDetail对象
     *
     * @param s
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //这里的字符串不再传用户名了,我们让他传json
        AuthParamsDto authParamsDto = null;
        //对字符串进行解析
        try {
            authParamsDto = JSON.parseObject(s, AuthParamsDto.class);
        } catch (Exception e) {
            throw new RuntimeException("认证参数有问题");
        }
        //然后我们就可以从authParamsDto对象中拿数据了

        //这里我们进行自己的校验规则
        String authType = authParamsDto.getAuthType();
        AuthService authService = applicationContext.getBean(authType + "_authservice", AuthService.class);
        //进行校验
        XcUserExt xcUserExt = authService.execute(authParamsDto);

        //获取userDetails对象
        UserDetails userDetails = getUserPrincipal(xcUserExt);

        //我们可能有很多业务,没有密码的校验,所以我们要重写密码的校验,我们自己实现;
        return userDetails;
    }

    /**
     * @param user 用户id，主键
     * @return com.xuecheng.ucenter.model.po.XcUser 用户信息
     * @description 查询用户信息
     * @author shiminghui
     * @date
     */
    public UserDetails getUserPrincipal(XcUserExt user) {
        //我们为了传输更多信息,可以对对于username那里填入json字符串
        //用户权限,如果不加报Cannot pass a null GrantedAuthority collection
        String[] authorities = {"p1"};
        //查询数据库获取用户权限
        List<XcMenu> xcMenus = xcMenuMapper.selectPermissionByUserId(user.getId());
        if (xcMenus.size() > 0) {
            List<String> list = xcMenus.stream().map(xcMenu -> xcMenu.getCode()).collect(Collectors.toList());
            authorities = list.toArray(new String[0]);
        }


        String password = user.getPassword();
        //为了安全在令牌中不放密码
        user.setPassword(null);
        //将user对象转json
        String userString = JSON.toJSONString(user);
        //创建UserDetails对象
        UserDetails userDetails = User.withUsername(userString).password(password).authorities(authorities).build();
        return userDetails;
    }
}
